package com.divemotor.ventarepuestosinternet.dao.impl;

import java.io.Serializable;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.transform.Transformers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.divemotor.ventarepuestosinternet.beans.adapter.ModeloFabricaAdapter;
import com.divemotor.ventarepuestosinternet.beans.adapter.ModeloFabricaDataAdapter;
import com.divemotor.ventarepuestosinternet.beans.form.ModeloFabricaBeanForm;
import com.divemotor.ventarepuestosinternet.dao.ModeloFabricaDAO;

import com.divemotor.ventarepuestosinternet.model.ModeloFabrica;
import com.divemotor.ventarepuestosinternet.model.ModeloFabricaPK;
import com.divemotor.ventarepuestosinternet.model.TipoComponente;
import com.divemotor.ventarepuestosinternet.util.Constantes;
import com.divemotor.ventarepuestosinternet.util.Paginacion;

@SuppressWarnings("unchecked")
@Repository(value = "modeloFabricaDAO")
public class ModeloFabricaDAOImpl implements ModeloFabricaDAO, Serializable {

	private static final long serialVersionUID = -8148495041651312746L;
	@Autowired
	private SessionFactory sessionFactory;

	@Override
	public ModeloFabrica obtenerPorId(ModeloFabrica modeloFabrica) {
		ModeloFabricaPK pk = modeloFabrica.getModeloFabricaPK();
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ModeloFabrica.class)
				.add(Restrictions.eq("modeloFabricaPK.idModeloFabrica", pk.getIdModeloFabrica()))
				.add(Restrictions.eq("modeloFabricaPK.idMarca", pk.getIdMarca()))
				.add(Restrictions.eq("modeloFabricaPK.idTipoComponente", pk.getIdTipoComponente()));
		return (ModeloFabrica) criteria.uniqueResult();
	}

	@Override
	public List<ModeloFabrica> listarPorTipoComponente(TipoComponente tipoComponente) {
		Criteria criteria = sessionFactory
				.getCurrentSession()
				.createCriteria(ModeloFabrica.class, "modeloFabrica")
				.createAlias("modeloFabrica.tipoComponente", "tipoComponente")
				.add(Restrictions.eq("tipoComponente.idTipoComponente",
						tipoComponente.getIdTipoComponente()))
				.addOrder(Order.asc("modeloFabrica.nombre"));
		return criteria.list();
	}

	@Override
	public List<ModeloFabrica> listarActivosPorTipoComponente(TipoComponente tipoComponente) {

		Criteria criteria = sessionFactory
				.getCurrentSession()
				.createCriteria(ModeloFabrica.class, "modeloFabrica")
				.createAlias("modeloFabrica.tipoComponente", "tipoComponente")
				.add(Restrictions.eq("tipoComponente.idTipoComponente",
						tipoComponente.getIdTipoComponente()))
				.add(Restrictions.eq("modeloFabrica.estado",
						Constantes.ESTADO_ACTIVO))
				.addOrder(Order.asc("modeloFabrica.nombre"));
		return criteria.list();
	}

	@Override
	public List<ModeloFabrica> listarActivosPorMarcaYTipoComponente(String marca, String tipoComponente) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ModeloFabrica.class, "modeloFabrica");
		criteria.add(Restrictions.eq("marca.codigoMarca",marca));
		criteria.add(Restrictions.eq("tipoComponente.idTipoComponente",tipoComponente));
		criteria.add(Restrictions.eq("modeloFabrica.estado",
						Constantes.ESTADO_ACTIVO));
		criteria.addOrder(Order.asc("modeloFabrica.nombre"));
		return criteria.list();
	}

	@Override
	public List<ModeloFabricaAdapter> buscarModeloFabricaPorDescripcionMarcaYTipoComponente(Paginacion paginacion, ModeloFabricaAdapter modeloFabrica) {
		Criteria criteriaCount = restriccionesModeloFabricaPorDescripcionMarcaYTipoComponente(modeloFabrica);
		criteriaCount.setProjection(Projections.rowCount());;
		
		Criteria criteria = restriccionesModeloFabricaPorDescripcionMarcaYTipoComponente(modeloFabrica);
		criteria.setFirstResult(paginacion.getInicioPagina());
		criteria.setMaxResults(paginacion.getFinPagina());

		if (!(paginacion.getOrdenarLabel() == null)) {
			if (paginacion.getDireccionOrden().equals("ASCENDING"))
				criteria.addOrder(Order.asc(paginacion.getOrdenarLabel()));
			else {
				criteria.addOrder(Order.desc(paginacion.getOrdenarLabel()));
			}
		}
		
		ProjectionList lista = Projections.projectionList();
		lista.add(Projections.property("modeloFabricaPK.idModeloFabrica"), "idModeloFabrica")
			 .add(Projections.property("modeloFabricaPK.idMarca"),"idMarca")
			 .add(Projections.property("modeloFabricaPK.idTipoComponente"),"idTipoComponente")
			 .add(Projections.property("nombre"),"nombre")
			 .add(Projections.property("modeloFabricaPK"),"modeloFabricaPK");
		
		paginacion.setRegTotal(Integer.valueOf(criteriaCount.uniqueResult().toString()));
		criteria.setProjection(lista);
		criteria.setResultTransformer(Transformers.aliasToBean(ModeloFabricaAdapter.class));
		return criteria.list();
	}
	
	private Criteria restriccionesModeloFabricaPorDescripcionMarcaYTipoComponente(ModeloFabricaAdapter modeloFabrica) {
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ModeloFabrica.class);
		criteria.createAlias("tipoComponente", "tipoComponente");
		criteria.createAlias("marca", "marca");
		
		String porc = Constantes.PORCENTAJE;
		
		String idTipoComponente = modeloFabrica.getIdTipoComponente();
		if (!Constantes.STR_NO_SELECCIONADO.equals(idTipoComponente)) {
			criteria.add(Restrictions.eq("tipoComponente.idTipoComponente", idTipoComponente));
		}

		String idMarca = modeloFabrica.getIdMarca();
		if (!Constantes.STR_NO_SELECCIONADO.equals(idMarca)) {
			criteria.add(Restrictions.eq("marca.codigoMarca", idMarca));
		}

		String idModeloFabrica = modeloFabrica.getIdModeloFabrica();
		if (StringUtils.isNotBlank(idModeloFabrica)) {
			criteria.add(Restrictions.like("modeloFabricaPK.idModeloFabrica", porc + idModeloFabrica + porc).ignoreCase());
		}

		String nombre = modeloFabrica.getNombre();
		if (StringUtils.isNotBlank(nombre)) {
			criteria.add(Restrictions.like("nombre", porc + nombre + porc).ignoreCase());
		}
		
		return criteria;
	}
	
	@Override
	public List<ModeloFabricaAdapter> buscarModelosFabricaAdapter(ModeloFabricaBeanForm modeloFabricaBeanForm){
		Criteria criteria = sessionFactory.getCurrentSession().createCriteria(ModeloFabrica.class, "modelo");
		criteria.createAlias("modelo.marca", "marca");
		criteria.createAlias("modelo.tipoComponente", "tipoComponente");
		
		criteria.setProjection(Projections.projectionList().add(Projections.property("modelo.modeloFabricaPK.idModeloFabrica"),"idModeloFabrica").
															add(Projections.property("modelo.nombre"),"nombre").
															add(Projections.property("tipoComponente.idTipoComponente"),"idTipoComponente").
															add(Projections.property("tipoComponente.nombre"),"nombreComponente").
														    add(Projections.property("marca.codigoMarca"),"idMarca").
														    add(Projections.property("marca.nombre"),"nombreMarca"));
		
		String marca 	   = modeloFabricaBeanForm.getMarca();
		if(marca != null && !marca.equals(Constantes.STR_NO_SELECCIONADO)){
			criteria.add(Restrictions.eq("marca.codigoMarca", marca));
		}
		
		String componente  = modeloFabricaBeanForm.getTipoComponente();
		if(componente != null && !componente.equals(Constantes.STR_NO_SELECCIONADO)){
			criteria.add(Restrictions.eq("tipoComponente.idTipoComponente", componente));
		}
		
		String codigo 	   = modeloFabricaBeanForm.getCodigo();
		if(StringUtils.isNotBlank(codigo)){
			criteria.add(Restrictions.eq("modelo.modeloFabricaPK.idModeloFabrica", codigo));
		}
		
		String descripcion = modeloFabricaBeanForm.getDescripcion();
		if(StringUtils.isNotBlank(descripcion)){
			criteria.add(Restrictions.eq("modelo.nombre", descripcion));
		}
		
		criteria.setResultTransformer(Transformers.aliasToBean(ModeloFabricaAdapter.class));
		return criteria.list();
	}
	
	@Override
	public List<ModeloFabricaDataAdapter> buscarComboModelosFabrica(){
		return sessionFactory.getCurrentSession().getNamedQuery("ModeloFabrica.obtenerModeloFabrica").list();
	}
	
}
